package com.aforce3.trailertracer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.media.j3d.Transform3D;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.aforce3.trailertracer.scenes.PointLight;
import com.aforce3.trailertracer.scenes.Rectangle;
import com.aforce3.trailertracer.scenes.SceneGroup;
import com.aforce3.trailertracer.scenes.Sphere;
import com.jimsproch.data.StringUtilities;


/**
 * Turns out, long videos need to be rendered one frame at a time due to massive memory requirements.
 * @author Jim Sproch
 *
 */
public class OfflineRenderer
{
	public static void main(String[] args) throws IOException
	{
		
		long time = System.currentTimeMillis();
		
		File dir = new File(System.getProperty("user.home")+File.separator+"TrailerTracer"+File.separator+time);
		dir.mkdirs();

		for(int i = 0; i < 250; i++)
		{
			FrameServer server = new FrameServer(getScene004(i));
			Renderer renderer = new Renderer(server);
			renderer.setPriority(Thread.MIN_PRIORITY);
			renderer.start();
			
			while(server.getJob().getPassesCompleted() < 1) try{Thread.sleep(1000);}catch(Exception e){}
			
			renderer.terminate();

			BufferedImage bi = (BufferedImage) server.getFrame(0);
			File outputfile = new File(dir.getAbsolutePath()+File.separator+time+"-"+StringUtilities.addLeadingZeros(i, 5)+".png");
			ImageIO.write(bi, "png", outputfile);
			
			System.gc();
		}
	}
	
	
	public static List<Frame> getVideoScene002(int i)
	{
		List<Frame> frames = new ArrayList<Frame>();

			BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);

			SceneGroup scene = new SceneGroup();

			Sphere s = new Sphere(new Point3d(0, 0, -30), 2f);
			Material m = new Material(new Color3f(0.1f, 0.1f, 0.1f), new Color3f(1, 0, 0), new Color3f(1, 0, 0), new Color3f(1, 1, 1), 0.5f, 30);
			s.setMaterial(m);
			scene.add(s);
			
			Sphere s2 = new Sphere(new Point3d(-4, 0, -25), 2f);
			Material m2 = new Material(new Color3f(1, 0.2f, 0.2f), new Color3f(1, 0, 0), new Color3f(1, 0, 0), new Color3f(1, 1, 1), 0.5f, 30);
			s2.setMaterial(m2);
			scene.add(s2);
			
			PointLight s3 = new PointLight(new Point3d(4, 0, -25), 0.2f, 0.6f);
			Material m3 = new Material(new Color3f(1, 1f, 0.2f), new Color3f(1, 1, 0), new Color3f(1, 0, 0), new Color3f(0.5f, 0.5f, 0.5f), 1, 30);
			
			
			s3.setMaterial(m3);
			scene.add(s3);
			
			double step = (2*Math.PI) / 250;

			Camera camera = new Camera(new Point3d(-15*Math.sin(i*step), 0, 60*Math.cos(i*step)), new Point3d(0, 0, -27), new Vector3d(0, 1, 0));

			frames.add(new Frame(image, camera, scene));
			
			return frames;
	}

	
	
	public static List<Frame> getVideoScene003(double i)
	{
		List<Frame> frames = new ArrayList<Frame>();

			BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);

			SceneGroup scene = new SceneGroup();

			Sphere s = new Sphere(new Point3d(0, 0, 0), 2f);
			Material m = new Material(new Color3f(0.1f, 0.1f, 0.1f), new Color3f(0, 0, 0), new Color3f(0.5f, 0.5f, 0.5f), new Color3f(1, 1, 1), 0.5f, 30);
			s.setMaterial(m);
			scene.add(s);
			
			PointLight s3 = new PointLight(new Point3d(4, 0, -25), 0.2f, 0.6f);
			Material m3 = new Material(new Color3f(1, 0f, 0f), new Color3f(1, 0, 0), new Color3f(1, 0, 0), new Color3f(1, 0, 0), 1, 30);
			
			
			s3.setMaterial(m3);
			scene.add(s3);

			Camera camera = new Camera(new Point3d(0, 0, 10), new Point3d(0, 0, 0), new Vector3d(0, 1, 0));

			frames.add(new Frame(image, camera, scene));
			
			return frames;
	}
	
	public static List<Frame> getScene004(int t)
	{
		List<Frame> frames = new ArrayList<Frame>();
		BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);

		Vector3d velocity1 = new Vector3d(0.04, -0.07, 0);
		velocity1.scale(t);
		
		Vector3d velocity2 = new Vector3d(-0.04, 0.07, -0.02);
		velocity2.scale(t);
		
		Vector3d velocity3 = new Vector3d(0, 0, -0.1);
		velocity3.scale(t);
		
		Transform3D transformation1 = new Transform3D();
		transformation1.setTranslation(velocity1);
		
		Transform3D transformation2 = new Transform3D();
		transformation2.setTranslation(velocity2);
		
		Transform3D transformation3 = new Transform3D();
		transformation3.setTranslation(velocity3);
		
		AxisAngle4d axis = new AxisAngle4d(0, 0, -1, 0.1 * t);
		
		Transform3D rotation = new Transform3D();
		rotation.set(axis);
		
		SceneGroup scene = new SceneGroup(new Point3d(-12, 12, -36), new Point3d(12, -12, -24));

		Sphere s = new Sphere(new Point3d(0, 0, -30), 2f);
		Material m = new Material(new Color3f(1f, 0.2f, 0.2f), new Color3f(0f, 0f, 0f), new Color3f(0.3f, 0f, 0f), new Color3f(1, 1, 1), 0.5f, 30);
		s.setMaterial(m);
		scene.add(s);
		
		s.SetTranform(transformation2);
		

		Sphere s2 = new Sphere(new Point3d(-4, 0, -25), 2f);
		Material m2 = new Material(new Color3f(1f, 0.2f, 0.2f), new Color3f(0f, 0f, 0f), new Color3f(0.3f, 0f, 0f), new Color3f(1, 1, 1), 0.5f, 30);
		s2.setMaterial(m2);
		scene.add(s2);
		
		s2.SetTranform(transformation1);
		

		PointLight s3 = new PointLight(new Point3d(4, 0, -23), 0.2f, 0.6f);
		Material m3 = new Material(new Color3f(1, 1f, 0.2f), new Color3f(1, 1, 0), new Color3f(1, 0, 0), new Color3f(1f, 1f, 1f), 1, 30);

		s3.setMaterial(m3);
		s3.SetTranform(transformation3);
		
		scene.add(s3);

		// strips
		Material m4 = new Material(new Color3f(0, 0.3f, 0.3f), new Color3f(0, 0, 0), new Color3f(0, 0.3f, 0.3f), new Color3f(1f, 1f, 1f), 1, 30);
		Rectangle r;
		for(float i = 0; i < 10; i++)
		{
			r = new Rectangle(new Point3d(-10 + 2 * i, -10, -35), new Point3d(-10 + 2 * i, 10, -35), new Point3d(-9 + 2 * i, 10, -35), new Point3d(-9 + 2 * i, -10, -35));
			r.setMaterial(m4);
			scene.add(r);
			
			if(i == 4 || i == 5) r.SetTranform(rotation);;
		}

		Material m5 = new Material(new Color3f(1f, 1f, 1f), new Color3f(1, 1, 1), new Color3f(1, 1, 1), new Color3f(1f, 1f, 1f), 1, 30);
		PointLight s5 = new PointLight(new Point3d(-4, 0, -28.5), 0.2f, 0.6f);
		s5.setMaterial(m5);
		scene.add(s5);

		// scene.add(b);
		
		
		scene.applyTransform();
		Camera camera = new Camera(new Point3d(0, 0, 10), new Point3d(0, 0, -1), new Vector3d(0, 1, 0));

		frames.add(new Frame(image, camera, scene));

		return frames;
	}
	
	
}
